from flask import Blueprint
from flask import request
from flask import render_template
from flask import flash
from flask import redirect
from flask import url_for
from flask import session

from app import db
from app.security import permission
from app.security import g

from app.wtforms.tipoItem_forms import TipoItemBuscar
from app.wtforms.tipoItem_forms import SeleccionarFase
from app.wtforms.tipoItem_forms import TipoItemEditable
from app.wtforms.tipoItem_forms import TipoItemNoEditable
from app.wtforms.tipoItem_forms import SeleccionarTipoItem
from app.wtforms.tipoItem_forms import ImportarTipoItem

from app.models.fase import Fase
from app.models.tipoItem import TipoItem
from app.models.atributo import Atributo




mod = Blueprint('tipoItems', __name__, url_prefix='/tipoItems')

@mod.route('/administracion/', methods=['GET', 'POST'])
@permission('ADMINISTRACION_TIPOITEMS')
def administracion_tipoItem():
    """
    Muestra en pantalla los tipos de items del proyecto seleccionado.
    Si no recibe algun filtro como parametro, lista todos los tipo de items.
    Si recibe algun filtro, muestra el tipo de item que cumple con el filtro indicado
    """
    
    #Obtenemos el proyecto seleccionado
    proyecto_seleccionado = g.proyecto
    
    # Obtenemos todas las fases del proyecto seleccionado
    fases =Fase.query.filter(Fase.proyecto == proyecto_seleccionado)
    # Hacemos una tupla con el nombre de la fase y su id
    lista_fases=[]
    for fase in fases:
        lista_fases.append((fase.id, fase.nombre)) 
        
    if(lista_fases != []):        
        # Obtenemos el formulario   
        form =  TipoItemBuscar(request.form)
       
        # Obtenemos el filtro
        nombreFilter = form.nombre.data
        
        if(nombreFilter == None):
            nombreFilter = ''
    
        # Recuperamor de la base de datos los items que coinciden con el filtro
        tipoItems = TipoItem.query.filter(TipoItem.nombre.like( '%'+nombreFilter+'%' ), TipoItem.proyecto_id == proyecto_seleccionado.id )
        tipoItems = tipoItems.all() 
     
        return render_template('tipoItem/administracion_tipoItem.html', form = form, tipoItems = tipoItems)
    
    else:
        flash('El proyecto no cuenta con fases donde se asignaran los tipos de items. Debe crear las fases para el proyecto seleccionado')
        return redirect(url_for('acceso.home'))
    


@mod.route('/seleccionarfasecrear/', methods=['GET', 'POST'])
@permission('CREAR_TIPOITEM')
def seleccionar_fase_crear():
    """
    Muestra en pantalla las fase que existen en el proyecto seleccionado.
    """
    
    # Obtenemos el formulario para listar las fases
    form = SeleccionarFase(request.form) 

    #Obtenemos el proyecto seleccionado
    proyecto_seleccionado = g.proyecto
    
    # Obtenemos todas las fases del proyecto seleccionado
    fases =Fase.query.filter(Fase.proyecto == proyecto_seleccionado)
    # Hacemos una tupla con el nombre de la fase y su id
    lista_fases=[]
    for fase in fases:
        lista_fases.append((fase.id, fase.nombre))                           
                      
    # Asignamos esa tupla de fases a la lista que va a ser visualizada  
    form.fases.choices = lista_fases
                    
    if form.validate_on_submit():
        # Obtenemos la fase seleccionada por el usuario 
        session['fase_id'] = form.fases.data
        return redirect(url_for('tipoItems.crear_tipoItem'))     
                 
    return render_template('tipoItem/seleccionar_fase.html', form = form)
    



@mod.route('/crear/', methods=['GET', 'POST'])
def crear_tipoItem():
    """
    Muestra en pantalla el formulario de creacion de tipo de items, valida los datos ingresados por
    el usuario, hace las validaciones de que el nombre no existan para la fase seleccionada y se hayan ingresado 
    los datos obligatorios. Luego almacena en la base de datos
    """
    
    #Obtenemos el proyecto seleccionado
    proyecto_seleccionado = g.proyecto
    #obtenemos la fase a donde importaremos el tipo de item seleccionado
    fase = session['fase_id']
    fase_seleccionada = Fase.query.filter_by(id=fase[0]).first()
    
        
    #el proyecto seleccionado  y la fase seleccionada deben estar con estado Pendiente
    if(proyecto_seleccionado.estado == 'Pendiente'): 
        if(fase_seleccionada.estado == 'Pendiente'):        
               
            # Obtenemos el formulario
            form = TipoItemEditable(request.form)  
                            
            # Obtenemos todos los tipo de items de la fase seleccionada
            tipoItems =TipoItem.query.filter(TipoItem.fase == fase_seleccionada)

            # Obtenemos todos los atributos existentes en la base de datos
            atributos =Atributo.query.all()
            
            # Hacemos una tupla con el nombre y el id del atributo
            lista_atributos=[]
            for atributo in atributos:
                lista_atributos.append((atributo.id, atributo.nombre))
            
            # Asignamos la tupla de atributos a la lista que va a ser visualizada en el checkbox  
            form.atributos.choices = lista_atributos
            
            # Se valida los datos ingresados en el formulario
            if form.validate_on_submit():
                contN = 0         
                # Comparamos que el nombre ingresado por el usuario no sea igual a uno existente
                if tipoItems != None:
                    for tipoind in tipoItems:
                        if form.nombre.data == tipoind.nombre:
                            contN = contN + 1
                        
                 
                # Si ya existe el nombre, no permitimos la creacion           
                if contN != 0:
                    flash("El nombre del tipo de item ya existe, elija otro", 'error-message')
                    # Redirigimos a la pagina de creacion
                    return redirect(url_for('tipoItems.crear_tipoItem', fase = fase_seleccionada.id))
                    
                # Si el nombre aun no existe
                else:
                    # Obtenemos los atributos seleccionados por el usuario
                    lista_atributos = []
                    for id_atributo in form.atributos.data:    
                        atributo = Atributo.query.filter_by(id=id_atributo).first()
                        lista_atributos.append(atributo)
                                       
                    nombre = form.nombre.data
                            
                    # Creamos el tipo de item
                    tipoItem_carga = TipoItem(nombre,lista_atributos,proyecto_seleccionado, fase_seleccionada)
                    db.session.add(tipoItem_carga)
                    db.session.commit()
                    
                    flash('El Tipo de Item ha sido registrado con exito')
                    # Una vez creado el tipo de item, se redirecciona a la pagina de administracion     
                    return redirect(url_for('tipoItems.administracion_tipoItem'))  
            return render_template('tipoItem/crear_tipoItem.html', form = form, fase_seleccionada=fase_seleccionada) 
        else:
            flash('No se pueden crear tipos de items para la fase seleccionada, la fase no se encuentra con estado PENDIENTE')  
            return redirect(url_for('tipoItems.administracion_tipoItem')) 
    else:
        flash('No se pueden crear tipos de items para el proyecto seleccionado, el proyecto no se encuentra con estado PENDIENTE')  
        return redirect(url_for('tipoItems.administracion_tipoItem'))
    
   
   
@mod.route('/modificar/<tipoItem>/', methods=['GET', 'POST'])
@permission('MODIFICAR_TIPOITEM')
def modificar_tipoItem(tipoItem):
    """
    Muestra en pantalla el formulario de modificacion de tipo de items, valida los datos ingresados por
    el usuario, hace las validaciones del nombre del nuevo tipo de item, que no existan para la fase seleccionada
    y se hayan ingresado los datos obligatorios. Luego almacena en base de datos los cambios
    :param tipoItem:
    id del tipo de item que se desea modificar
    """ 
    
    #Obtenemos el proyecto seleccionado
    proyecto_seleccionado = g.proyecto
    #Obtenemos el tipo de item seleccionado
    tipoItem_seleccionado = TipoItem.query.filter_by(id=tipoItem).first()
    #obtenemos la fase del tipo de item seleccionado
    fase_seleccionada = Fase.query.filter_by(id=tipoItem_seleccionado.fase.id).first()
    
    #el proyecto seleccionado  y la fase seleccionada deben estar con estado Pendiente
    if(proyecto_seleccionado.estado == 'Pendiente'): 
        if(fase_seleccionada.estado == 'Pendiente'):
    
            #obtenemos el formulario 
            form = TipoItemEditable(request.form)
                    
            #Obtenemos todos los tipo de items de la fase seleccionada
            tipoItems =TipoItem.query.filter(TipoItem.fase == fase_seleccionada)
    
            # Obtenemos todos los atributos existentes en la base de datos
            atributos =Atributo.query.all()     
      
            # Hacemos una tupla con el nombre y el id del atributo
            lista_atributos=[]
            for atributo in atributos:
                lista_atributos.append((atributo.id, atributo.nombre))
            
            # Asignamos la tupla de atributos a la lista que va a ser visualizada en el checkbox  
            form.atributos.choices = lista_atributos 
                 
            #Se valida los datos ingresados en el formulario
            if form.validate_on_submit():
                contN = 0         
                # Comparamos que el nombre ingresado por el usuario no sea igual 
                # a uno existente en la fase seleccionada
                if tipoItems != None:
                    for tipoind in tipoItems:
                        if tipoItem_seleccionado.id != tipoind.id:
                            if form.nombre.data == tipoind.nombre:
                                contN = contN + 1
    
                 
                # Si ya existe el nombre, no permitimos la modificacion          
                if contN != 0:
                    flash("El nombre del tipo de item ya existe, debe ingresar otro", 'error-message')
                    # Redirigimos a la pagina de modificar
                    return redirect(url_for('tipoItems.modificar_tipoItem', tipoItem = tipoItem_seleccionado.id))
                    
                # Si el nombre aun no existe
                else: 
                    # Obtenemos los atributos seleccionados por el usuario
                    lista_atributos = []
                    for id_atributo in form.atributos.data:    
                        atributo = Atributo.query.filter_by(id=id_atributo).first()
                        lista_atributos.append(atributo)
                        
                    # Realizamos los cambios     
                    tipoItem_seleccionado.setNombre(form.nombre.data)
                    tipoItem_seleccionado.setAtributo(lista_atributos)
                        
                    #Almacenamos el tipo de item modificado en la base de datos
                    db.session.add(tipoItem_seleccionado)
                    db.session.commit()
                    # Retornamos a la pagina de administracion de tipo de items
                    flash('El tipo de item ha sido actualizado con exito')
                    return redirect(url_for('tipoItems.administracion_tipoItem')) 
             
            
            # Mostramos en el formulario los datos actuales del tipo de item seleccionado
            form.nombre.data = tipoItem_seleccionado.nombre
            form.fase.data = fase_seleccionada.nombre
            # Obtenemos los atributos que el tipo de item seleccionado tiene actualmente sin modificacion
            atributos_seleccionados = []
            for atributo_sec in tipoItem_seleccionado.atributo:
                atributos_seleccionados.append(atributo_sec.id)
              
            # Mostramos seleccionados en el checkbox los atributos 
            form.atributos.data = atributos_seleccionados
                
            return render_template('tipoItem/modificar_tipoItem.html', form = form, tipoItem_seleccionado=tipoItem_seleccionado)  
        
        else:
            flash('No se pueden modificar tipos de items para la fase seleccionada, la fase no se encuentra con estado PENDIENTE')  
            return redirect(url_for('tipoItems.administracion_tipoItem')) 
    else:
        flash('No se pueden modificar tipos de items para el proyecto seleccionado, el proyecto no se encuentra con estado PENDIENTE')  
        return redirect(url_for('tipoItems.administracion_tipoItem'))
 
 
    
@mod.route('/consultar/<tipoItem>/', methods=['GET', 'POST'])
@permission('VER_TIPOITEM')
def consultar_tipoItem(tipoItem):
    """
    Muestra en pantalla el formulario de consulta de tipos de items, muestra todos los datos del
    tipo de item seleccionado
    :param tipoItem:
    id del tipo de item que se desea consultar
    """
    
    #Obtenemos el tipo de item seleccionado
    tipoItem_seleccionado = TipoItem.query.filter_by(id=tipoItem).first()

    # Obtenemos el formulario
    form = TipoItemNoEditable(request.form)
        
    # Hacemos una tupla con el nombre y el id de los atributos del tipo de item
    atributos_seleccionados = []
    for atributo in tipoItem_seleccionado.atributo:
        atributos_seleccionados.append((atributo.id, atributo.nombre))
        
        
    # Mostramos en el formulario los datos actuales del tipo de item seleccionado
    form.nombre.data = tipoItem_seleccionado.nombre
    form.fase.data = tipoItem_seleccionado.fase.nombre
    form.atributos.choices = atributos_seleccionados
           
        
    if form.validate_on_submit():
        #Cuando el usuario presiona aceptar, redirigimos a la pagina de administracion de tipo de items
        return redirect(url_for('tipoItems.administracion_tipoItem'))
        
    return render_template('tipoItem/consultar_tipoItem.html', form = form, 
                               tipoItem_seleccionado=tipoItem_seleccionado)
    
        
        


@mod.route('/eliminar/<tipoItem>/', methods=['GET', 'POST'])
@permission('ELIMINAR_TIPOITEM')
def eliminar_tipoItem(tipoItem):
    
    #Obtenemos el proyecto seleccionado
    proyecto_seleccionado = g.proyecto
    #Obtenemos el tipo de item seleccionado
    tipoItem_seleccionado = TipoItem.query.filter_by(id=tipoItem).first()
    #obtenemos la fase del tipo de item seleccionado
    fase_seleccionada = Fase.query.filter_by(id=tipoItem_seleccionado.fase.id).first()
    
    #el proyecto seleccionado  y la fase seleccionada deben estar con estado Pendiente
    if(proyecto_seleccionado.estado == 'Pendiente'): 
        if(fase_seleccionada.estado == 'Pendiente'):
            
            # Borramos de la base de datos el tipo de item seleccionado
            db.session.delete(tipoItem_seleccionado)
            db.session.commit()
            # Redirigimos a la pagina de administracion de tipo de items
            flash('El tipo de item ha sido eliminada con exito')
            return redirect(url_for('tipoItems.administracion_tipoItem'))
        else:
            flash('No se pueden eliminar tipos de items para la fase seleccionada, la fase no se encuentra con estado PENDIENTE')  
            return redirect(url_for('tipoItems.administracion_tipoItem')) 
    else:
        flash('No se pueden eliminar tipos de items para el proyecto seleccionado, el proyecto no se encuentra con estado PENDIENTE')  
        return redirect(url_for('tipoItems.administracion_tipoItem'))    




@mod.route('/seleccionarfase/', methods=['GET', 'POST'])
@permission('CREAR_TIPOITEM')
def seleccionar_fase():
    """
    Muestra en pantalla las fase que existen en el proyecto seleccionado.
    """
    
    # Obtenemos el formulario para listar las fases
    form = SeleccionarFase(request.form) 

    #Obtenemos el proyecto seleccionado
    proyecto_seleccionado = g.proyecto
    
    # Obtenemos todas las fases del proyecto seleccionado
    fases =Fase.query.filter(Fase.proyecto == proyecto_seleccionado)
    # Hacemos una tupla con el nombre de la fase y su id
    lista_fases=[]
    for fase in fases:
        lista_fases.append((fase.id, fase.nombre)) 
        
         
    # Asignamos esa tupla de fases a la lista que va a ser visualizada  
    form.fases.choices = lista_fases
            
    if form.validate_on_submit():
        # Obtenemos la fase seleccionada por el usuario 
        session['fase_id'] = form.fases.data
        return redirect(url_for('tipoItems.seleccionar_tipoItem'))    
    return render_template('tipoItem/seleccionar_fase.html', form = form)
   


@mod.route('/seleccionar/', methods=['GET', 'POST'])
def seleccionar_tipoItem():
    """
    Muestra en pantalla los tipos de items que existen en el proyecto seleccionado.
    """
    
    #Obtenemos el proyecto seleccionado
    proyecto_seleccionado = g.proyecto
    #obtenemos la fase a donde importaremos el tipo de item seleccionado
    fase = session['fase_id']
    fase_seleccionada = Fase.query.filter_by(id=fase[0]).first()  
    
    #el proyecto seleccionado  y la fase seleccionada deben estar con estado Pendiente
    if(proyecto_seleccionado.estado == 'Pendiente'): 
        if(fase_seleccionada.estado == 'Pendiente'):
            # Obtenemos el formulario para listar los tipo de items
            form = SeleccionarTipoItem(request.form)                      
                            
            # Obtenemos todos los tipo de items existentes en la base de datos
            tipoItems =TipoItem.query.all()
            # Hacemos una tupla con el id y nombre del tipo de item, el proyecto y la fase donde fue creado
            lista_tipoItems=[]
            for tipoItem in tipoItems:
                lista_tipoItems.append((tipoItem.id, tipoItem.nombre +" "+ tipoItem.fase.nombre +" "+ tipoItem.proyecto.nombre))               
           
            # Asignamos esa tupla de tipo de items a la lista que va a ser visualizada  
            form.tipoItems.choices = lista_tipoItems
            form.fase.data = fase_seleccionada.nombre
            
            if form.validate_on_submit():
                session['tipoitem_id'] = form.tipoItems.data
                return redirect(url_for('tipoItems.importar_tipoItem'))       
                     
            return render_template('tipoItem/seleccionar_tipoItem.html', form = form)
        else:
            flash('No se pueden importar tipos de items para la fase seleccionada, la fase no se encuentra con estado PENDIENTE')  
            return redirect(url_for('tipoItems.administracion_tipoItem')) 
    else:
        flash('No se pueden importar tipos de items para el proyecto seleccionado, el proyecto no se encuentra con estado PENDIENTE')  
        return redirect(url_for('tipoItems.administracion_tipoItem'))
    

  
@mod.route('/importar/', methods=['GET', 'POST'])
def importar_tipoItem():
    
    """
    Muestra en pantalla el formulario de importar tipos de items
    """    
    # Obtenemos el formulario
    form = ImportarTipoItem(request.form)
        
    # Obtenemos el tipo de item seleccionado  
    tipoitem = session['tipoitem_id'] 
    tipoItem_seleccionado = TipoItem.query.filter_by(id=tipoitem[0]).first()             
    # Hacemos una tupla con el nombre y el id de los atributos del tipo de item
    lista_atributos = []
    atributos_seleccionados = []
    for atributo in tipoItem_seleccionado.atributo:
        atributos_seleccionados.append((atributo.id, atributo.nombre))
        lista_atributos.append(atributo)
                
        
    # Se aceptan los datos del tipo de item
    if form.validate_on_submit():
        
        #Obtenemos el proyecto seleccionado
        proyecto_seleccionado = g.proyecto
        #obtenemos la fase a donde se importara el tipo de item seleccionado
        fase = session['fase_id']
        fase_seleccionada = Fase.query.filter_by(id=fase[0]).first()  
         
        #obtenemos todos los tipos de items de la fase seleccionada
        tipoItems = TipoItem.query.filter(TipoItem.fase==fase_seleccionada)
        
        contN = 0         
        # Comparamos que el nombre ingresado por el usuario no sea igual 
        # a uno existente en la fase seleccionada
        if tipoItems != None:
            for tipoind in tipoItems:
                if form.nombre.data == tipoind.nombre:
                    contN = contN + 1
                        
                 
        # Si ya existe el nombre, no permitimos la creacion           
        if contN != 0:
            flash("El nombre del tipo de item ya existe, debe ingresar otro", 'error-message')
            # Redirigimos a la pagina de importacion
            return redirect(url_for('tipoItems.importar_tipoItem', tipoItem = tipoItem_seleccionado.id))
            
        # Si el nombre aun no existe
        else:
            nombre = form.nombre.data
                
            # Creamos el tipo de item
            tipoItem_carga = TipoItem(nombre, lista_atributos, proyecto_seleccionado, fase_seleccionada)
            db.session.add(tipoItem_carga)
            db.session.commit()               
            flash('El tipo de item ha sido registrado con exito')
            # Una vez creado el nuevo tipo de item, se redirecciona a la pagina de administracion     
            return redirect(url_for('tipoItems.administracion_tipoItem')) 
    
    # Mostramos en el formulario los datos actuales del tipo de item seleccionado
    form.nombre.data = tipoItem_seleccionado.nombre
    form.atributos.choices = atributos_seleccionados
    
    return render_template('tipoItem/importar_tipoItem.html', form = form)


    